module.exports = () => {
    // 返回一个 Koa 中间件
    return async (ctx, next) => {
        /**
         * 先获取请求路径，检查看看是否需要校验登录
         * 为什么有些接口需要校验登录呢？
         * 因为有些接口，比如：修改用户信息，我们要保证只能修改自己的信息，不可以改其他用户的信息
         * 所以就需要知道该请求的用户是谁。
         * 怎么知道呢？
         * 就是在请求的 header 中添加一个 token 字段，然后服务器去解析这个 token
         * 如果能够成功解析 token，我们就可以知道这个请求是谁发出的了
         * 而且前后端规定，token 都统一放在请求的 header 中
         */
        if (ctx.path === '/login' || ctx.path === '/register') {
            await next();
        } else {
            // 取出请求 header 中的 token 字段
            const token = ctx.headers.token;
            // 如果没有 token，我们就认为前端用户都没登录，那就返回未登录响应
            if (!token) {
                ctx.body = {
                    code: 401,
                    message: 'token字段不存在',
                };
                return;
            }
            // token 存在，我们需要校验 token 的合法性，有可能是伪造的 token
            // 如果是正确的 token（也就是服务器生成的 token）那么就可以解析成功
            // 解析成功，会返回 token 所代表的用户的信息
            try {
                const user = ctx.helper.checkToken(token);
                // 我们往 ctx 对象上添加一个 user 属性，值就是我们解析 token 拿到的 token 所包含的用户信息
                ctx.user = user;
            } catch (error) {
                // token 解析有问题
                if (error.name === 'JsonWebTokenError') {
                    ctx.body = {
                        code: 401,
                        message: '无效的token',
                    };
                    return;
                }

                if (error.name === 'TokenExpiredError') {
                    ctx.body = {
                        code: 401,
                        message: 'token已过期',
                    };
                    return;
                }
            }
            // 校验通过，继续向下执行
            await next();
        }
    };
};
